#include <stdio.h>
#include <stdlib.h>
#include "get_keyboard.h"

#define CNT 5//地图数量
#define ROAD 0
#define WALL 1
#define BOX  2
#define TERM 3
#define MOUS 4
#define BINT BOX+TERM
#define MINT MOUS+TERM

#define MAX_ROW 15//地图的行列
#define MAX_COL 15
#define STEP 10//反悔的步数

int initboard[MAX_ROW][MAX_COL];//初始地图
int board[MAX_ROW][MAX_COL];

int row = 0,col = 0;//真实地图的大小
int boxnum = 0;//箱子的个数
int mx = 0,my = 0;//老鼠的位置
int actiond[STEP] = {};//记录移动的方向
int pushbox[STEP] = {};
int stepnum = 0;//

void load(int n){
	char filename[24] = {};
	sprintf(filename,"%d.txt",n);
	FILE *fp = fopen(filename,"r");
	if (fp == NULL){
		return;
	}
	fscanf(fp,"%d %d",&row,&col);
	int i,j;
	for(i=0;i<row;i++){
		for(j=0;j<col;j++){
			fscanf(fp,"%d",&initboard[i][j]);
		}
	}
}

int init(){
	int i,j;
	boxnum = 0;
	for (i=0;i<row;i++){
		for(j=0;j<col;j++){
			board[i][j] = initboard[i][j];	
			if(board[i][j] == BOX || board[i][j] == BINT){
			++boxnum;
	    	}
	    	if(board[i][j] == MOUS || board[i][j] == MINT){
			mx = i;
			my = j;
	    	}
	    }
	}
}

int success(){
	int bint = 0;
	int i,j;
	for(i=0;i<row;i++){
		for(j=0;j<col;j++){
			if(board[i][j] == BINT){
				++bint;
			}
		}
	}
	if(bint == boxnum){
		return 1;
	}
	else {return 0;}
}

void show(){
int i,j;
   for(i=0;i<row;i++)
   {  for(j=0;j<col;j++)
      {   
        if (board[i][j] == ROAD){
           printf(" ");
        }else if (board[i][j] == WALL){
           printf("#");
        }else if (board[i][j] == TERM){
           printf("0");
        }else if (board[i][j] == BOX || board[i][j] == BINT){
           printf("@");
        }else if (board[i][j] == MOUS || board[i][j] == MINT){
           printf("&");}
      }
      printf("\n");
   }
}

int move(int stepx,int stepy){
	int nx = mx + stepx;
  	int ny = my + stepy;//下一位置
  	int nnx = mx + stepx + stepx;
  	int nny = my + stepy + stepy;
    if(board[nx][ny] == ROAD || board[nx][ny] == TERM){
       board[mx][my] = board[mx][my] - MOUS;
       board[nx][ny] = board[nx][ny] + MOUS;
       mx = nx;
       my = ny;
       return 1;
    }else if (board[nx][ny] == BOX || board[nx][ny] == BINT){
     	if (board[nnx][nny] == ROAD || board[nnx][nny]  == TERM){
        	board[nnx][nny] = board[nnx][nny] + BOX;
          	board[nx][ny] = board[nx][ny] - BOX;
          	board[mx][my] = board[mx][my] - MOUS;
         	board[nx][ny] = board[nx][ny] + MOUS;
          	mx = nx;
         	my = ny;
          	return 2;
        }
     }
  return 0;	
}
void moveback(int stepx,int stepy){
	int rx = mx - stepx;
	int ry = my - stepy;
	board[mx][my] = board[mx][my] - MOUS;
	board[rx][ry] = board[rx][ry] + MOUS;
	if (pushbox[stepnum] == 1){
		int bx = mx + stepx;
		int by = my + stepy;
		board[bx][by] = board[bx][by] - BOX;
		board[mx][my] = board[mx][my] + BOX;
	}
	mx = rx;
	my = ry;
	actiond[stepnum] = 0;
	pushbox[stepnum] = 0;
}

void back(){
	if(stepnum>0){
		--stepnum;
		if (actiond[stepnum] == KEY_LEFT){
			moveback(0,-1);
		}else if (actiond[stepnum] == KEY_RIGHT){
			moveback(0,1);
		}else if (actiond[stepnum] == KEY_UP){
			moveback(-1,0);
		}else if (actiond[stepnum] == KEY_DOWN){
			moveback(1,0);
		}
	}
}
void run(){
	int i;
	for(i=1;i<=CNT;i++){
		load(i);//加载地图
		init();//初始化
		while(1){
			system("clear");
			show();
			if(success()){//完成关卡跳出
				printf("恭喜\n");
				sleep(1);
				break;
			}
			int key = get_keyboard();
			int ret = 0;
        	if (key == KEY_LEFT){
           		ret = move(0,-1);
        	} else if (key == KEY_RIGHT){//向右移
           		ret = move(0,1);
        	} else if (key == KEY_UP){//向上移
           		ret = move(-1,0);
        	} else if (key == KEY_DOWN){//向下移
          		ret = move(1,0);
       		} else if (key == KEY_q){
        		exit(0);
       		} else if (key == KEY_r){
        		init();
        	} else if (key == KEY_b){
        		back();
        	} if (ret != 0){//ret记录移动类型
        		if(stepnum<STEP){
		    		actiond[stepnum] = key;//记录移动方向
		    		pushbox[stepnum] = 0;
		    	if (ret == 2){
		    		pushbox[stepnum] = 1;
		    	}
		    		++stepnum;
        		}else {
        			int i;
        			for (i=1;i<stepnum;i++){
        				actiond[i-1] = actiond[i];
        				pushbox[i-1] = pushbox[i];
        			}
        				actiond[stepnum-1] =key;
        				pushbox[stepnum-1] = 0;
        			if (ret == 2){
        				pushbox[stepnum-1] = 1;
        			}	
        		}
        	}
		}
	}
	
}
int main(){
	run();
	return 0;
}
